package com.wkbb.basic.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.wkbb.basic.feign.DoorFeignService;
import com.wkbb.basic.mapper.*;
import com.wkbb.basic.model.*;
import com.wkbb.basic.service.*;
import com.wkbb.basic.thread.*;
import com.wkbb.basic.utils.ExcelErrorTipUtil;
import com.wkbb.basic.utils.ExcelFieldUtil;
import com.wkbb.basic.utils.FillEmptyHeadImgUtil;
import com.wkbb.basic.vo.StudentEditInfoVo;
import com.wkbb.basic.vo.StudentManageEditVo;
import com.wkbb.common.base.BaseServiceImpl;
import com.wkbb.common.constants.ErrorCode;
import com.wkbb.common.dto.ResultDTO;
import com.wkbb.common.dto.basic.*;
import com.wkbb.common.dto.order.PayUserCommodityInfoDto;
import com.wkbb.common.enums.*;
import com.wkbb.common.handler.JsonUtil;
import com.wkbb.common.redis.RedisTemplateUtil;
import com.wkbb.common.utils.*;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;

/**
 * @author dengjingyuan
 * @date 2019-07-04 14:37
 */
@Service
@Slf4j
public class StudentServiceImpl extends BaseServiceImpl<Student> implements StudentService {

    @Autowired
    private DistrictMapper districtMapper;
    @Autowired
    private SchoolMapper schoolMapper;
    @Autowired
    private StudentMapper studentMapper;

    @Autowired
    private UserMapper userMapper;

    @Autowired
    private UserService userService;

    @Autowired
    private UserInfoMapper userInfoMapper;

    @Autowired
    private FamilyService familyService;

    @Autowired
    private FamilyMapper familyMapper;

    @Autowired
    private UserInfoService userInfoService;

    @Autowired
    private GradeMapper gradeMapper;

    @Autowired
    private ClassInfoMapper classInfoMapper;

    @Autowired
    private UserOpenService userOpenService;

    @Autowired
    private RedisTemplateUtil redisTemplateUtil;

    @Autowired
    private OrganizationService organizationService;

    @Autowired
    private ImportLogService importLogService;

    @Autowired
    @Lazy
    private XmppService xmppService;

    @Autowired
    private DoorFeignService doorFeignService;

    @Autowired
    private YouTuService youTuService;

    @Autowired
    private OrganizationMapper organizationMapper;

    @Autowired
    private NationalityService nationalityService;


    @Autowired
    public void setMapper(StudentMapper mapper) {
        super.setMapper(mapper);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Long insert(StudentInfoDto studentInfoDto, String userName) {
        User user = userMapper.getByPrimaryKey(studentInfoDto.getUserId());
        Long userId;

        if (null != user) {
            userId = user.getId();
            //插入学生表
            insertStudent(studentInfoDto, userId, userName);
            //有用户信息,修改roleType  JSON权限
            Object roleType = userService.updateRoleTypeJson(user.getRoleType(), null,
                    Short.parseShort("" + RoleTypeEnum.STUDENT.getValue()), null, studentInfoDto.getOrgId(), user.getId());
            user.setRoleType(roleType);
            userMapper.update(user);
            //更新redis
            userService.updateUserInfo(studentInfoDto.getOrgId(), userId);
        } else {
            User newUser = new User();
            BeanUtils.copyProperties(studentInfoDto, newUser);
            newUser.setRoleType(userService.updateRoleTypeJson(null, null,
                    Short.parseShort("" + RoleTypeEnum.STUDENT.getValue()), null, studentInfoDto.getOrgId(), null));
            newUser.setStatus(true);
            newUser.setUserCode(UuIdUtil.getUserCodeByUUId());
            userService.insert(studentInfoDto.getOrgId(), newUser, RoleTypeEnum.STUDENT.getValue(), studentInfoDto.getSex(), null, studentInfoDto.getSmartWxUserId(), studentInfoDto.getIsSmartSubscribe());

            userId = newUser.getId();
            UserInfo userInfo = new UserInfo();
            BeanUtils.copyProperties(studentInfoDto, userInfo);
            if (!StringUtils.isEmpty(studentInfoDto.getHeadImgUrl())) {
                userInfo.setHeadImgMd5(userService.getImageMD5(studentInfoDto.getHeadImgUrl()));
            }
            userInfo.setUserId(userId);
            userInfo.setBirthDate(studentInfoDto.getBirthDate());
            userInfoMapper.insert(userInfo);
            //插入学生表
            insertStudent(studentInfoDto, userId, userName);
        }

        return userId;
    }

    private void insertStudent(StudentInfoDto studentInfoDto, Long userId, String userName) {
        Student student = new Student();
        BeanUtils.copyProperties(studentInfoDto, student);
        student.setUserId(userId);
        student.setCreateBy(userName);
        student.setUpdateBy(userName);
        student.setUserType(1);
        student.setEnterDate(studentInfoDto.getEnterDate());
        student.setAutoCreate(false);
        studentMapper.insert(student);
        //学生班级关联
        studentMapper.insertClassStudent(student);
    }


    /**
     * 更新学生信息
     *
     * @param studentManageEditVo      学生家长信息
     * @param createBy                 操作人
     * @param isSendToXmppOrSendToDoor 是否同步处理XMPP 1是0否
     * @param isClearAddressBook       是否清理跟这个用户相关的其他用户的通讯录缓存
     * @throws Exception 抛出异常
     */
    @Override
    public Long insert(StudentManageEditVo studentManageEditVo, String createBy, Boolean isSendToXmppOrSendToDoor, Boolean isClearAddressBook) throws Exception {
        StudentInfoDto studentInfoDto = studentManageEditVo.getStudentInfoDto();

        String headImg = FillEmptyHeadImgUtil.checkHeadImg(studentInfoDto.getSex(), RoleTypeEnum.STUDENT.getValue(), studentInfoDto.getHeadImgUrl(), false);
        if (!StringUtil.isNullOrBlank(headImg)) {
            log.info("默认头像地址：" + headImg);
            studentInfoDto.setHeadImgUrl(headImg);
        }

        Long studentUserId = null;
        if (null == studentInfoDto.getUserId()) {

            //插入后返回学生userId
            studentUserId = insert(studentInfoDto, createBy);
            studentInfoDto.setUserId(studentUserId);

            /*if (isSendToXmppOrSendToDoor) {
                //xmpp推送更新用户通行权限
                //BasicThreadPoolUtil.getExecutorService(new BasicThreadPoolUtil(serviceConfig)).execute(new SynUserAccessXmppTask(doorFeignService, studentInfoDto.getOrgId(), studentUserId, RoleTypeEnum.STUDENT, xmppService, null, null, null, true, false, true, false,(short)RoleTypeEnum.STUDENT.getValue()));
                ThreadPoolUtil.addPoolTask(new SynUserAccessXmppTask(doorFeignService, studentInfoDto.getOrgId(), studentUserId, RoleTypeEnum.STUDENT, xmppService, null, null, null, true, false, true, false, (short) RoleTypeEnum.STUDENT.getValue(), null));
            }*/
        } else {
            studentUserId = studentInfoDto.getUserId();
        }

        List<FamilyInfoDto> familyInfoList = studentManageEditVo.getFamilyInfoList();
        if (familyInfoList == null || familyInfoList.isEmpty()) {
            return studentUserId;
        }

        //家长自动入群

        for (FamilyInfoDto familyInfoDto : familyInfoList) {
            if (StringUtil.isNotEmpty(familyInfoDto.getName()) && StringUtil.isNotEmpty(familyInfoDto.getMobile()) && (null != familyInfoDto.getRelationType())) {
                List<FamilyInfoDto> familyInfoListByClassIdList = new ArrayList<>();
                //如果家长已存在，则直接跳过
                boolean familyIsExist = checkFamilyExist(studentInfoDto.getOrgId(), familyInfoDto.getMobile(), studentUserId, null);
                if (familyIsExist) {
                    continue;
                }

                //新增需要更新家长的卡号和手机号
                familyService.updateFamilyHistory(familyInfoDto);
                familyInfoDto = insertFamily(familyInfoDto, studentInfoDto, createBy, isSendToXmppOrSendToDoor);
                familyInfoListByClassIdList.add(familyInfoDto);
                if (isClearAddressBook) {
                    log.info("**********家长新增,删除宝宝所在班级的所有老师通讯录**********");
                    ThreadPoolUtil.addPoolTask(new BacisDeleteAddressBookKeyTask(familyInfoDto.getUserId(), AddressListEnum.FAMILY.getValue(), familyInfoDto.getOrgId(), userOpenService));
                    log.info("**********家长新增,删除宝宝所在班级的所有老师通讯录**********");
                }
            }
        }

        //如果是后台新增家长自动入群、导入不触发
//        if (isSendToXmppOrSendToDoor) {
//            ThreadPoolUtil.addTask(new ImSaveFamilyTask(classInfoService, familyInfoListByClassIdList));
//        }
        return studentUserId;
    }

    private FamilyInfoDto insertFamily(FamilyInfoDto familyInfoDto, StudentInfoDto studentInfoDto, String createBy, Boolean flag) throws Exception {
        //检查必填数据
        if (familyInfoDto == null || familyInfoDto.getRelationType() == null || familyInfoDto.getRelationType() == 0) {
            return null;
        }

        //继承学生信息
        copyStudentInfo(familyInfoDto, studentInfoDto);

        //若该家长用户不存在，新增一个用户，再添加家长信息
        if (familyInfoDto.getUserId() == null || familyInfoDto.getUserId() == 0) {
            return familyService.insertWithFamily(familyInfoDto, createBy, flag);
        } else {
            //家长用户存在情况下新增家长，取原先手机号
            User user = userService.getByPrimaryKey(familyInfoDto.getUserId());
            String mobile = user.getMobile();
            familyInfoDto.setMobile(mobile);

            //否家长用户已存在，则只添加家长信息
            familyInfoDto.setId(null);
            return familyService.insertFamily(familyInfoDto, familyInfoDto.getUserId(), createBy, flag);
        }
    }

    /**
     * 家长信息加入学生信息
     *
     * @param familyInfoDto  家长信息
     * @param studentInfoDto 学生信息
     */
    private void copyStudentInfo(FamilyInfoDto familyInfoDto, StudentInfoDto studentInfoDto) {
        if (studentInfoDto.getUserId() != null) {
            familyInfoDto.setStudentUserId(studentInfoDto.getUserId());
        }
        if (!StringUtil.isNullOrBlank(studentInfoDto.getName())) {
            familyInfoDto.setStudentName(studentInfoDto.getName());
        }
        if (studentInfoDto.getOrgId() != null) {
            familyInfoDto.setOrgId(studentInfoDto.getOrgId());
        }
        if (studentInfoDto.getGradeId() != null) {
            familyInfoDto.setGradeId(studentInfoDto.getGradeId());
        }
        if (studentInfoDto.getClassId() != null) {
            familyInfoDto.setClassId(studentInfoDto.getClassId());
        }
        if (!StringUtil.isNullOrBlank(studentInfoDto.getAreaCode())) {
            familyInfoDto.setAreaCode(studentInfoDto.getAreaCode());
        }
        if (!StringUtil.isNullOrBlank(studentInfoDto.getProvinceCode())) {
            familyInfoDto.setProvinceCode(studentInfoDto.getProvinceCode());
        }
        if (!StringUtil.isNullOrBlank(studentInfoDto.getCityCode())) {
            familyInfoDto.setCityCode(studentInfoDto.getCityCode());
        }
        if (!StringUtil.isNullOrBlank(studentInfoDto.getArea())) {
            familyInfoDto.setArea(studentInfoDto.getArea());
        }
        if (!StringUtil.isNullOrBlank(studentInfoDto.getProvince())) {
            familyInfoDto.setProvince(studentInfoDto.getProvince());
        }
        if (!StringUtil.isNullOrBlank(studentInfoDto.getCity())) {
            familyInfoDto.setCity(studentInfoDto.getCity());
        }
        if (studentInfoDto.getAddr() != null) {
            familyInfoDto.setAddr(studentInfoDto.getAddr());
        }
    }

    @Override
    public void update(StudentInfoDto studentInfoDto, String userName) throws Exception {
        update(studentInfoDto, userName, false);
        //xmpp推送更新用户通行权限
//        ThreadPoolUtil.addPoolTask(new SynUserAccessXmppTask(doorFeignService, studentInfoDto.getOrgId(), studentInfoDto.getUserId(), RoleTypeEnum.STUDENT, xmppService, null, null, null, true, false, true, false, (short) RoleTypeEnum.STUDENT.getValue(), null));
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public ResultDTO update(StudentInfoDto studentInfoDto, String userName, boolean isBack) throws Exception {
        //当头像为空,默认设置头像.否则走正常变更
        Boolean flag = false;
        if (!StringUtil.isEmptyIgnoreBlank(studentInfoDto.getHeadImgUrl())) {
            flag = true;
        }

        String headImg = FillEmptyHeadImgUtil.checkHeadImg(studentInfoDto.getSex(), RoleTypeEnum.STUDENT.getValue(), studentInfoDto.getHeadImgUrl(), flag);
        if (!StringUtil.isNullOrBlank(headImg)) {
            log.info("默认头像地址：" + headImg);
            studentInfoDto.setHeadImgUrl(headImg);
        }

        User user = userMapper.getByPrimaryKey(studentInfoDto.getUserId());
        BeanUtils.copyProperties(studentInfoDto, user);
        //copy之后会覆盖掉userId
        user.setId(studentInfoDto.getUserId());
        Object roleType = userService.updateRoleTypeJson(user.getRoleType(), Short.parseShort("" + RoleTypeEnum.STUDENT.getValue()), Short.parseShort("" + RoleTypeEnum.STUDENT.getValue()), studentInfoDto.getOldOrgId(), studentInfoDto.getOrgId(), studentInfoDto.getUserId());
        user.setRoleType(roleType);
        user.setHeadImgUrl(studentInfoDto.getHeadImgUrl());
        if (null != studentInfoDto.getIsSmartSubscribe()) {
            user.setIsSmartSubscribe(studentInfoDto.getIsSmartSubscribe());
        }

        userService.update(studentInfoDto.getOrgId(), user, RoleTypeEnum.STUDENT.getValue(), isBack, studentInfoDto.getSmartWxUserId(), studentInfoDto.getIsSmartSubscribe());

        Student student = studentMapper.getByUserId(studentInfoDto.getUserId());

        //删除前一个班级关联
        studentMapper.deleteClassStudent(student);

        BeanUtils.copyProperties(studentInfoDto, student);
        student.setUserId(user.getId());
        student.setUpdateBy(userName);
        student.setEnterDate(studentInfoDto.getEnterDate());

        //班级关联
        studentMapper.insertClassStudent(student);

        log.info("-----------------------------updateStudent:{},{}",isBack, JsonUtil.objectToJson(student));
        if (isBack) {
            //如果学生调换了班级,查询新班级的年级是否已经变更,已变更则设置新的年级
//            Long newClassId = studentInfoDto.getClassId();
//            Long oriClassId = studentInfoDto.getOriClassId();
//            if (null != oriClassId && !newClassId.equals(oriClassId)) {
//                ClassInfo newClassInfo = classInfoMapper.getByPrimaryKey(newClassId);
//                if (student.getGradeId().longValue() != newClassInfo.getGradeId().longValue()) {
//                    student.setGradeId(newClassInfo.getGradeId());
//                }
//            }
            studentMapper.updateBack(student);
        } else {
            studentMapper.update(student);
        }

        Map<String, Object> params = new HashMap<>(1);
        params.put("userId", studentInfoDto.getUserId());
        UserInfo userInfo = userInfoMapper.getByMapParams(params);
        BeanUtils.copyProperties(studentInfoDto, userInfo);
        if (!StringUtils.isEmpty(studentInfoDto.getHeadImgUrl())) {
            userInfo.setHeadImgMd5(userService.getImageMD5(studentInfoDto.getHeadImgUrl()));
        }
        userInfo.setUserId(user.getId());
        userInfo.setBirthDate(studentInfoDto.getBirthDate());
        userInfoService.update(userInfo, isBack);

        return new ResultDTO();
    }

    @Override
    public void update(StudentManageEditVo studentManageEditVo, String updateBy, Boolean flag) throws Exception {
        StudentInfoDto studentInfoDto = studentManageEditVo.getStudentInfoDto();

        update(studentInfoDto, updateBy, true);

        /*if (flag) {
            //xmpp推送更新用户通行权限
            ThreadPoolUtil.addPoolTask(new SynUserAccessXmppTask(doorFeignService, studentInfoDto.getOrgId(), studentInfoDto.getUserId(), RoleTypeEnum.STUDENT, xmppService, null, null, null, true, false, true, false, (short) RoleTypeEnum.STUDENT.getValue(), null));
        }*/


//        //IM相关开始---------------------------学生调换班级---------------------------
//        log.info("IM相关开始---------------------------学生调换班级---------------------------");
//        //前端新增一个原学生班级的字段oriClassId,用来记录原班级
//        Long orgId = studentInfoDto.getOrgId();
//        Long newClassId = studentInfoDto.getClassId();
//        Long oriClassId = studentInfoDto.getOriClassId();
//        Long studentUserId = studentInfoDto.getUserId();
//        log.info("IM相关开始,学生调换班级,orgId={},newClassId={},oriClassId={},studentUserId={}---------------------------", orgId, newClassId, oriClassId, studentUserId);
//        List<Family> familyList = new ArrayList<>();
//        if (null != oriClassId && !newClassId.equals(oriClassId)) {
//            //开始调换班级,该学生对应所有家长入新群退老群
//            //此学生全部家长退群
//            //查询出此学生对应的全部家长,并循环让此家长退群
//            familyList = getFamilyByStudentId(orgId, oriClassId, studentUserId);
//            //1.此学生全部家长退群
////            for (Family family : familyList) {
////                userOpenService.operateGroupUser(ImOperGroupTypeEnum.OUT_GROUP.getValue(), orgId, oriClassId, family.getUserId(), studentUserId, RoleTypeEnum.FAMILY.getValue(), UserTypeEnum.FAMILY.getValue(), false);
////            }
//
//            //换班需要清园长、班主任、任课老师的通讯录
//            log.info("******换班需要清园长、班主任、任课老师的通讯录******");
//            ThreadPoolUtil.addPoolTask(new BacisDeleteAddressBookKeyTask(null, AddressListEnum.PRINCIPAL.getValue(), orgId, userOpenService));//清园长通讯录
//            ThreadPoolUtil.addPoolTask(new BacisDeleteAddressBookKeyTask(studentUserId, AddressListEnum.FAMILY.getValue(), orgId, userOpenService));//清老师的通讯录
//        }
//        log.info("IM相关结束---------------------------学生调换班级---------------------------");
        //IM相关结束---------------------------学生调换班级---------------------------

//        List<FamilyInfoDto> familyInfoDtoList = manageFamily(studentManageEditVo, updateBy, flag);
//        //新添加的家长自动入群
//        if(CollectionUtils.isNotEmpty(familyInfoDtoList)){
//            ThreadPoolUtil.addTask(new ImSaveFamilyTask(classInfoService, familyInfoDtoList));
//        }
    }

    private List<Family> getFamilyByStudentId(Long orgId, Long oriClassId, Long studentUserId) {
        List<Family> familyList;
        Map<String, Object> paramMap = new HashMap<>();
        paramMap.put("orgId", orgId);
        paramMap.put("classId", oriClassId);
        paramMap.put("studentId", studentUserId);
        familyList = familyMapper.getListByMapParams(paramMap);
        return familyList;
    }

    /**
     * 更新学生时处理家长信息
     *
     * @param studentManageEditVo 学生编辑信息
     * @param updateBy            操作人
     */
    private List<FamilyInfoDto> manageFamily(StudentManageEditVo studentManageEditVo, String updateBy, Boolean flag) throws Exception {
        StudentInfoDto studentInfoDto = studentManageEditVo.getStudentInfoDto();
        List<FamilyInfoDto> familyInfoList = studentManageEditVo.getFamilyInfoList();

        //对比删除阶段
        deleteFamily(studentManageEditVo, updateBy);

        List<FamilyInfoDto> familyInfoListByClassIdList = new ArrayList<>();

        if (familyInfoList == null || familyInfoList.isEmpty()) {
            return familyInfoListByClassIdList;
        }

        for (FamilyInfoDto familyInfoDto : familyInfoList) {
            if (familyInfoDto == null) {
                break;
            }

            //若不是与已存在家长关联，新增一个家长
            if (familyInfoDto.getUserId() == null) {
                FamilyInfoDto insertFamilyInfoDto = insertFamily(familyInfoDto, studentInfoDto, updateBy, flag);
                familyInfoListByClassIdList.add(insertFamilyInfoDto);
            } else {
                //检查该家长是否同改学生已有关联关系
                Family family = getBindFamily(familyInfoDto.getUserId(), studentInfoDto.getUserId());

                //若有关联关系，直接更新原来的数据
                if (family != null) {
                    //如果家长有调班,返回对象
                    FamilyInfoDto updateFamilyInfoDto = updateFamily(familyInfoDto, studentInfoDto, updateBy);

                    if (null != updateFamilyInfoDto) {
                        familyInfoListByClassIdList.add(updateFamilyInfoDto);
                    }
                    try {
                        log.info("**********家长修改,删除宝宝所在班级的所有老师通讯录**********");
                        redisTemplateUtil.delete(userOpenService.getAddressBookRedisKey(familyInfoDto.getOrgId(), "family", "only", familyInfoDto.getUserId()));
                        log.info("**********家长修改,删除宝宝所在班级的所有老师通讯录**********");
                    } catch (Exception e) {
                        log.error("**********家长修改,删除宝宝所在班级的所有老师通讯录异常**********");
                    }
                } else {
                    //若无关联关系，则新增一个家长
                    FamilyInfoDto insertFamilyInfoDto = insertFamily(familyInfoDto, studentInfoDto, updateBy, flag);
                    familyInfoListByClassIdList.add(insertFamilyInfoDto);
                }
            }
        }
        return familyInfoListByClassIdList;
    }

    private void deleteFamily(StudentManageEditVo studentManageEditVo, String updateBy) throws Exception {
        StudentInfoDto studentInfoDto = studentManageEditVo.getStudentInfoDto();
        List<FamilyInfoDto> familyInfoList = studentManageEditVo.getFamilyInfoList();

        //查找当前学生之前的家长
        Map<String, Object> params = new HashMap<>(1);
        params.put("studentId", studentInfoDto.getUserId());
        List<Family> familyList = familyService.getListByMapParams(params);
        if (familyList == null || familyList.isEmpty()) {
            return;
        }

        //循环检测删除家长
        for (Family family : familyList) {
            family.setUpdateBy(updateBy);
            //如果是没有传入家长，直接把所有家长从库里删除
            if (familyInfoList == null || familyInfoList.isEmpty()) {
                deleteFamily(updateBy, family);
                continue;
            }

            //如果没有从传入的家长里找到userId相同的家长，把该家长从库里删除
            boolean deleteFlag = true;
            for (FamilyInfoDto familyInfoDto : familyInfoList) {
                if (family.getUserId().equals(familyInfoDto.getUserId())) {
                    deleteFlag = false;
                    break;
                }
            }
            if (deleteFlag) {
                deleteFamily(updateBy, family);
            }
        }
    }

    private void deleteFamily(String updateBy, Family family) throws Exception {
        familyService.deleteFamily(Collections.singletonList(family.getId()), updateBy);

        //删除家长对应删除IM账号缓存
        /*ResultDTO<Object> imUserRedis = tcCloudFeignService.getImUserRedis(family.getUserId(), family.getOrgId(), (short) RoleTypeEnum.FAMILY.getValue(), UserTypeEnum.FAMILY.getValue().shortValue());
        if (ResultDTO.checkSuccess(imUserRedis) && null != imUserRedis.getData()) {
            log.info("----------清除该用户IM缓存----------userId:{}", family.getUserId());
            redisTemplateUtil.delete(imUserRedis.getData().toString());
        }*/
        singleFamilyOutGroup(family);
    }

    /**
     * 单个家长退群
     *
     * @param family
     */
    private ResultDTO singleFamilyOutGroup(Family family) {
        Long orgId = family.getOrgId();
        Long classId = family.getClassId();
        ResultDTO resultDto = userOpenService.operateGroupUser(ImOperGroupTypeEnum.OUT_GROUP.getValue(), orgId, classId, family.getUserId(), family.getStudentUserId(), RoleTypeEnum.FAMILY.getValue(), UserTypeEnum.FAMILY.getValue(), true);
        log.info("-----单个家长退群-----{}", JSONObject.toJSONString(resultDto));
        return resultDto;
    }

    /**
     * 更新家长信息
     *
     * @param familyInfoDto  家长信息
     * @param studentInfoDto 学生信息
     * @param updateBy       操作人
     */
    private FamilyInfoDto updateFamily(FamilyInfoDto familyInfoDto, StudentInfoDto studentInfoDto, String updateBy) {
        try {
            Boolean flag = false;

            copyStudentInfo(familyInfoDto, studentInfoDto);

            //如果更换了班级,同时更新家长的gradeId和classId
            //如果学生调换了班级,查询新班级的年级是否已经变更,已变更则设置新的年级
            Long newClassId = studentInfoDto.getClassId();
            Long oriClassId = studentInfoDto.getOriClassId();
            if (null != oriClassId && !newClassId.equals(oriClassId)) {
                ClassInfo newClassInfo = classInfoMapper.getByPrimaryKey(newClassId);
                if (familyInfoDto.getGradeId().longValue() != newClassInfo.getGradeId().longValue()) {
                    familyInfoDto.setGradeId(newClassInfo.getGradeId());
                }
                flag = true;
            }
            familyService.update(familyInfoDto, updateBy);
            if (flag) {
                return familyInfoDto;
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 检查该家长是否同改学生已有关联关系
     *
     * @param familyUserId  家长用户ID
     * @param studentUserId 学生用户ID
     */
    private Family getBindFamily(Long familyUserId, Long studentUserId) {
        Map<String, Object> params = new HashMap<>();
        params.put("userId", familyUserId);
        params.put("studentId", studentUserId);
        List<Family> family = null;
        try {
            family = familyService.getListByMapParams(params);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return family != null && !family.isEmpty() ? family.get(0) : null;
    }

    @Transactional(rollbackFor = Exception.class)
    public Map<String, Object> delete(List<Long> ids, String deleteBy, Integer type) throws Exception {
        Map<String, Object> result = new HashMap<String, Object>();
        List<Student> studentList = new ArrayList<Student>();

        if (ids.isEmpty()) {
            result.put("resultDTO", new ResultDTO(ErrorCode.PARAM_MISSING));
            return result;
        }

        //定义删除成功的用户,定义失败的
        String fail = "";
        Boolean flag = true;
        for (Long id : ids) {

            if (id == null || id == 0) {
                result.put("resultDTO", new ResultDTO(ErrorCode.PARAM_MISSING));
                return result;
            }

//            User user = null;
//            Student student = studentMapper.getByPrimaryKey(id);
            /*if (null != student) {
                user = userMapper.getByPrimaryKey(student.getUserId());
                //查询此学生是否有有效订单
                try {
                    ResultDTO userCommodityByUserIdResultDto = orderFeignService.getUserCommodityByUserId(user.getId());
                    log.info("----------查询此学生是否有有效订单结果----------result:{}", userCommodityByUserIdResultDto.getData());
                    if (ResultDTO.checkSuccess(userCommodityByUserIdResultDto)) {
                        fail = getDeleteName(fail, user.getName(), false);
                        flag = false;
                    }
                }
                catch (Exception e)
                {
                    log.error("查询学生订单异常:{}",e.getMessage());
                }
            }*/
        }
        if (flag || type.equals(SubmitEnum.SUBMIT.getValue())) {
            for (Long id : ids) {
                Student student = studentMapper.getByPrimaryKey(id);
                if (null != student) {
                    Long orgId = student.getOrgId();
                    Long classId = student.getClassId();
                    Long studentUserId = student.getUserId();

                    ResultDTO resultDto = operateGroupUser(ImOperGroupTypeEnum.OUT_GROUP.getValue(), orgId, classId, studentUserId, true);
                    if (!resultDto.isSuccess()) {
                        result.put("resultDTO", resultDto);
                        return result;
                    }

                    familyService.deleteByStudentId(student.getOrgId(), student.getUserId(), deleteBy);
                    userService.deleteUserInfo(student.getOrgId(), student.getUserId(), RoleTypeEnum.STUDENT.getValue());

                    Student deleteStudent = new Student();
                    deleteStudent.setId(id);
                    deleteStudent.setStatus(false);
                    deleteStudent.setUpdateBy(deleteBy);
                    studentMapper.update(deleteStudent);

                    studentMapper.delClassStudent(studentUserId);

                    studentList.add(student);
                }
            }
        }

        //如果是正常提交返回成功,否则返回系统提示
        if (type.equals(SubmitEnum.SYSTEMERROR.getValue())) {
            result.put("resultDTO", new ResultDTO(fail));
        } else {
            result.put("resultDTO", new ResultDTO());
        }
        result.put("studentList", studentList);
        return result;
    }

    @Override
    public ResultDTO deleteStudent(List<Long> ids, String deleteBy, Integer type) throws Exception {
        Map<String, Object> result = delete(ids, deleteBy, type);

        ResultDTO resultDTO = result.get("resultDTO") == null ? null : (ResultDTO) result.get("resultDTO");
//        List<Student> studentList = result.get("studentList") == null ? null : (List<Student>) result.get("studentList");

        if (resultDTO != null) {
            return resultDTO;
        }

//        studentList.forEach(
//                student -> {
//                    //xmpp推送更新用户通行权限
//                    ThreadPoolUtil.addPoolTask(new SynUserAccessXmppTask(doorFeignService, student.getOrgId(), student.getUserId(), RoleTypeEnum.STUDENT, 1, xmppService, null, null, null, true, false, true, false, (short) RoleTypeEnum.STUDENT.getValue(), null));
//                }
//        );

        return new ResultDTO(resultDTO);
    }

    /**
     * 此学生的全部家长退群
     *
     * @param operationType     入群或退群
     * @param orgId             学生的学校ID
     * @param classId           学生的班级ID
     * @param studentUserId     学生的ID
     * @param isDeleteImAccount 是否删除IM账号
     * @return
     */
    private ResultDTO operateGroupUser(Integer operationType, Long orgId, Long classId, Long studentUserId, Boolean isDeleteImAccount) {
        //查询出此学生对应的全部家长,并循环让此家长退群
        Map<String, Object> paramMap = new HashMap<>();
        paramMap.put("orgId", orgId);
        paramMap.put("classId", classId);
        paramMap.put("studentId", studentUserId);
        List<Family> familyList = familyMapper.getListByMapParams(paramMap);
        for (Family family : familyList) {
            //先查询出家长所在的群的imGroupId
            ResultDTO resultDto = userOpenService.operateGroupUser(operationType, orgId, classId, family.getUserId(), studentUserId, RoleTypeEnum.FAMILY.getValue(), UserTypeEnum.FAMILY.getValue(), isDeleteImAccount);
            if (!resultDto.isSuccess()) {
                return resultDto;
            }
        }
        return new ResultDTO();
    }

    @Override
    public StudentEditInfoVo getStudentInfoById(Long id) {
        return studentMapper.getStudentInfoById(id);
    }

    @Override
    public StudentManageEditVo getStudentInfoWithFamilyListById(Long id) {
        HashMap<String, Object> params = new HashMap<>(1);
        params.put("id", id);
        return studentMapper.getStudentInfoWithFamilyList(params);
    }

    @Override
    public PageInfo<StudentInfoDto> getStudentInfoPageList(Map<String, Object> params, Integer pageNo, Integer pageSize) {
        if (pageNo == null || pageSize == null) {
            return null;
        }
        Page<StudentInfoDto> page = PageHelper.startPage(pageNo, pageSize, true);
        PageInfo<StudentInfoDto> pageInfo = new PageInfo<StudentInfoDto>(studentMapper.getStudentInfoPageList(params));

        // setStudentInfo(pageInfo.getList());

        pageInfo.setTotal(page.getTotal());

        return pageInfo;
    }

    /**
     * 设置学生对象某些属性
     *
     * @param list
     */
    private void setStudentInfo(List<StudentInfoDto> list) {
        //加上是否已经上传人脸判断
        if (CollectionUtils.isNotEmpty(list)) {
            //因为orgId是必须传的参数,因此获取AccountId可以提取出来
            Long accountId = userOpenService.getAccountIdByOrgId(list.get(0).getOrgId());
            for (StudentInfoDto studentInfoDto : list) {
                studentInfoDto.setAccountId(accountId);
                Boolean hasUploadFace = youTuService.checkHasUploadFace(studentInfoDto.getOrgId(), studentInfoDto.getUserId());
                studentInfoDto.setHasUploadFace(hasUploadFace);
            }
        }
    }

    @Override
    public PageInfo<StudentInfoDto> getStudentInfoPageByClassId(Map<String, Object> params, Integer pageNo, Integer pageSize) {
        if (pageNo == null || pageSize == null) {
            return null;
        }
        Page<StudentInfoDto> page = PageHelper.startPage(pageNo, pageSize, true);
        PageInfo<StudentInfoDto> pageInfo = new PageInfo<StudentInfoDto>(getStudentInfoListByClassId(params));

        setStudentInfo(pageInfo.getList());

        pageInfo.setTotal(page.getTotal());

        return pageInfo;
    }

    @Override
    public List<StudentInfoDto> getStudentInfoList(Map<String, Object> params) {
        return studentMapper.getStudentInfoList(params);
    }

    @Override
    public List<StudentInfoDto> getStudentInfoListByClassId(Map<String, Object> params) {
        return studentMapper.getStudentInfoList(params);
    }

    @Override
    public List<UserInfoDto> getGuardianInfoList(Long userId) {
        Map<String, Object> params = new HashMap<>();
        params.put("userId", userId);
        Student userInfo = studentMapper.getByUserId(userId);
        if (null != userInfo) {
            params.put("orgId", userInfo.getOrgId());
            return studentMapper.getGuardianInfoList(params);
        }
        return null;
    }

    @Override
    public StudentInfoDto getStudentInfoByMobile(Map<String, Object> params) {
        return studentMapper.getStudentInfoByMobile(params);
    }

    //propagation = Propagation.SUPPORTS, 如果存在一个事务，支持当前事务。如果没有事务，则非事务的执行
    //propagation = NOT_SUPPORTED, 以非事务方式运行，如果当前存在事务，则把当前事务挂起
    //propagation = NEVER：以非事务方式运行，如果当前存在事务，则抛出异常
    @Override
    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public ResultDTO<Map<String, Object>> saveData(UserDto userDto, Long orgId, List<Object[]> data, String flag, Integer currentRow, Boolean isClearAddressBook) throws Exception {
        return importNewOrgStudentData(userDto, orgId, data, currentRow, flag, isClearAddressBook);
    }

    /**
     * {0=学校名称*, 1=年级*,2=班级*, 3=学生姓名*, 4=性别*, 5=学号}
     * {0=学校名称*, 1=班级*, 2=学生姓名*, 3=性别*, 4=学号, 5=出生日期, 6=学生卡号, 7=入学日期, 8=民族, 9=手机号, 10=身份证号,
     * 11=姓名, 12=关系*, 13=手机号码*, 14=姓名, 15=关系, 16=手机号码, 17=姓名, 18=关系, 19=手机号码, 20=姓名,
     * 21=关系, 22=手机号码, 23=姓名, 24=关系, 25=手机号码, 26=姓名, 27=关系, 28=手机号码, 29=姓名, 30=关系, 31=手机号码}
     *
     * @param userDto
     * @param selectedOrgId
     * @param data
     * @param currentRow
     * @param isK12
     * @param isClearAddressBook
     * @return
     * @throws Exception
     */
    private ResultDTO<Map<String, Object>> importNewOrgStudentData(UserDto userDto, Long selectedOrgId, List<Object[]> data, Integer currentRow, String isK12, Boolean isClearAddressBook) throws Exception {
        if (null == selectedOrgId || CollectionUtils.isEmpty(data)) {
            return new ResultDTO<>(ErrorCode.PARAM_MISSING);
        }
        //定义一个Map,用于存储每条数据,什么原因而失败
        Map<String, Object> returnMap = new HashMap();
        List<StudentInfoDto> importFailList = new ArrayList();
        List<StudentInfoDto> importOkList = new ArrayList<>();
        Long newOrgId = null;

//        Organization oriOrganization = organizationMapper.getByPrimaryKey(selectedOrgId);
//        默认是幼儿园
//        Integer orgType = OrganizationTypeEnum.KINDERGARTEN.getValue();
//        if (null != oriOrganization) {
//            orgType = oriOrganization.getOrgType();
//        }

        List<NationalityDto> nationalityList = nationalityService.getNationalityList();

        for (Object[] objects : data) {
            StudentInfoDto studentInfoDto = changeToEntityForNew(objects);
            //阶段1,先检查所有字段的合法性,不合法直接跳至下一条数据,再去验证系统中数据有效性,通过则导入
            //判断学校名称(1、非空 2、学校名称和当前PC端选择的学校名称一致，可正常导入)
            if (StringUtils.isEmpty(studentInfoDto.getOrgName())) {
                ExcelErrorTipUtil.notNullValid(ExcelFieldUtil.ORG_NAME, studentInfoDto, importFailList);
                continue;
            }
            Organization organization = organizationService.getOrgByName(null, studentInfoDto.getOrgName());
            if (null != organization && (selectedOrgId == 1L ||  organization.getId().longValue() == selectedOrgId.longValue())) {
                newOrgId = organization.getId();
            } else {
                ExcelErrorTipUtil.validField(ErrorCode.SELECTED_ORG_WRONG, studentInfoDto, importFailList);
                continue;
            }
            //获取班级(1、非空 2、并且班级在本学校存在，可正常导入)
            ClassInfo newClassInfo = null;
            String className = studentInfoDto.getClassName();
            if (!StringUtils.isEmpty(className)) {
                //根据newOrgId和className查询newClassId
                Map<String, Object> params = new HashMap<String, Object>();
                params.put("orgId", newOrgId);
                params.put("gradeName", studentInfoDto.getGradeName());
                params.put("className", className);
                newClassInfo = classInfoMapper.getByMapParams(params);
                log.info("newOrgId:"+newOrgId);
                if (null == newClassInfo) {
                    ExcelErrorTipUtil.validField(ErrorCode.CLASS_NOT_EXIST_ERROR, studentInfoDto, importFailList);
                    continue;
                }
            } else {
                ExcelErrorTipUtil.notNullValid(ExcelFieldUtil.CLASS_NAME, studentInfoDto, importFailList);
                continue;
            }
            //学生姓名
            //1、非空
            //2、姓名长度在8位数（包含8位），可正常导入
            //3、学生姓名可以重复
            String studentName = studentInfoDto.getName();
            if (ExcelErrorTipUtil.checkUserNameField(studentName, ExcelFieldUtil.STUDENT_NAME, studentInfoDto, importFailList, true)) {
                continue;
            }
            //学生性别
            //性别(1、非空 2、性别：男或女)
            String sex = studentInfoDto.getSex();
            if (ExcelErrorTipUtil.checkSexField(sex, studentInfoDto, importFailList)) {
                continue;
            }
            //学生学号
            //K12学校
            //1、非空
            //2、学号长度不超过20位字符（包含20位）
            //3、学号无中文，无特殊符号
            //4、学号在本班内唯一，可正常导入

            //幼儿园
            //1、非必填
            //2、学号长度不超过20位字符（包含20位）
            //3、学号无中文，无特殊符号，
            //4、学号在本班内唯一，可正常导入
            String studentNo = studentInfoDto.getStudentNo();
            if (isK12.equals("k12")) {
                if (StringUtils.isEmpty(studentNo)) {
                    ExcelErrorTipUtil.notNullValid(ExcelFieldUtil.STUDENT_NO, studentInfoDto, importFailList);
                    continue;
                }
            }
            //填写了学号,开始做验证
            if (StringUtil.isNotEmpty(studentNo)) {
                Integer maxLength = 20;
                if (studentNo.trim().length() > maxLength) {
                    String fieldErrorMsg = ExcelErrorTipUtil.fieldErrorTip(ErrorCode.FIELD_LENGTH_ERROR, ExcelFieldUtil.STUDENT_NO, maxLength);
                    ExcelErrorTipUtil.validField(fieldErrorMsg, studentInfoDto, importFailList);
                    continue;
                } else if (VerifyUtil.checkCharacters(studentNo) || VerifyUtil.checkZhCharacters(studentNo)) {
                    String fieldErrorMsg = ExcelErrorTipUtil.fieldErrorTip(ErrorCode.FIELD_CHAR_ZH_ERROR, ExcelFieldUtil.STUDENT_NO);
                    ExcelErrorTipUtil.validField(fieldErrorMsg, studentInfoDto, importFailList);
                    continue;
                }
                //学生学号要在学校唯一
                List<Student> studentList = checkStudentNoUnique(newOrgId, studentNo, newClassInfo.getId());
                if (CollectionUtils.isNotEmpty(studentList)) {
                    String fieldErrorMsg = ExcelErrorTipUtil.fieldErrorTip(ErrorCode.NO_EXIST_ERROR, ExcelFieldUtil.STUDENT_NO, ExcelFieldUtil.STUDENT_NO);
                    ExcelErrorTipUtil.validField(fieldErrorMsg, studentInfoDto, importFailList);
                    continue;
                }
            }
            //出生日期可以为空
//            Date birthDate = null;
//            Object birthDateObj = objects[5];
//            if (ExcelErrorTipUtil.checkDateField(birthDateObj, studentInfoDto, importFailList, ExcelFieldUtil.BIRTH_DATE)) {
//                continue;
//            } else {
//                birthDate = ExcelErrorTipUtil.formatObjectDate(birthDateObj);
//            }
            //学生卡号可以为空
            //1、非必填
            //2、卡号在表内是唯一的，并且在系统中也是唯一的
            //3、卡号位数不超过10位字符（包含10位）
            //4、卡号是数字或英文，没有特殊符号，多张卡号用半角逗号隔开，
            //5、不超过8张学生卡号
//            String studentCardNo = objects[6].toString();
//            if (StringUtil.isNotEmpty(studentCardNo)) {
//                String[] cardNos = studentCardNo.split(",");
//                if (cardNos.length > 8) {
//                    ExcelErrorTipUtil.validField(ErrorCode.STUDENT_CARD_COUNT_ERROR, studentInfoDto, importFailList);
//                    continue;
//                } else if (cardNos.length == 0) {
//                    String fieldErrorMsg = ExcelErrorTipUtil.fieldErrorTip(ErrorCode.CHAR_SPLIT_ERROR, ExcelFieldUtil.STUDENT_CARD_NO);
//                    ExcelErrorTipUtil.validField(fieldErrorMsg, studentInfoDto, importFailList);
//                    continue;
//                }
//                boolean validLenFlag = false;
//                boolean validCharFlag = false;
//                boolean validUniqueFlag = false;
//                Integer maxLength = 10;
//                for (String cardNo : cardNos) {
//                    if (cardNo.trim().length() > maxLength) {
//                        validLenFlag = true;
//                        break;
//                    } else if (VerifyUtil.checkCharacters(cardNo) || VerifyUtil.checkZhCharacters(cardNo)) {
//                        validCharFlag = true;
//                        break;
//                    }
//                    //判断唯一,系统唯一,并不是学校里唯一
//                    if (userService.checkCardNoUnique(cardNo, newOrgId)) {
//                        validUniqueFlag = true;
//                        break;
//                    }
//                }
//                if (validLenFlag) {
//                    String fieldErrorMsg = ExcelErrorTipUtil.fieldErrorTip(ErrorCode.FIELD_LENGTH_ERROR, ExcelFieldUtil.STUDENT_CARD_NO, maxLength);
//                    ExcelErrorTipUtil.validField(fieldErrorMsg, studentInfoDto, importFailList);
//                    continue;
//                }
//                if (validCharFlag) {
//                    String fieldErrorMsg = ExcelErrorTipUtil.fieldErrorTip(ErrorCode.FIELD_CHAR_ZH_ERROR, ExcelFieldUtil.STUDENT_CARD_NO);
//                    ExcelErrorTipUtil.validField(fieldErrorMsg, studentInfoDto, importFailList);
//                    continue;
//                }
//                if (validUniqueFlag) {
//                    String fieldErrorMsg = ExcelErrorTipUtil.fieldErrorTip(ErrorCode.NO_EXIST_ERROR, ExcelFieldUtil.STUDENT_CARD_NO, ExcelFieldUtil.STUDENT_CARD_NO);
//                    ExcelErrorTipUtil.validField(fieldErrorMsg, studentInfoDto, importFailList);
//                    continue;
//                }
//
//            }
            //7=入学日期, 8=民族, 9=手机号, 10=身份证号,
            //入学日期可以为空
//            Date enterDate = null;
//            Object enterDateObj = objects[7];
//            if (ExcelErrorTipUtil.checkDateField(enterDateObj, studentInfoDto, importFailList, ExcelFieldUtil.STUDENT_ENTER_DATE)) {
//                continue;
//            } else {
//                enterDate = ExcelErrorTipUtil.formatObjectDate(enterDateObj);
//            }
//            //民族
//            String nationality = objects[8].toString();
//            if (ExcelErrorTipUtil.checkNationalityField(nationality, nationalityList, studentInfoDto, importFailList)) {
//                continue;
//            }
            //学生手机号
            //1、非必填
            //2、手机号段正常，位数满足11位，
            //3、学生手机号在表内和系统内是唯一的，没有重复
//            String studentMobile = objects[9].toString();
//            if (ExcelErrorTipUtil.checkMobileField(studentMobile, ExcelFieldUtil.MOBILE, studentInfoDto, importFailList, false)) {
//                continue;
//            }
            //学生身份证
//            String studentIdCard = objects[10].toString();
//            if (StringUtil.isNotEmpty(studentIdCard)) {
//                if (!IdCardUtil.isValidatedAllIdcard(studentIdCard)) {
//                    String fieldErrorMsg = ExcelErrorTipUtil.fieldErrorTip(ErrorCode.FILED_ERROR, ExcelFieldUtil.ID_CARD, ExcelFieldUtil.ID_CARD);
//                    ExcelErrorTipUtil.validField(fieldErrorMsg, studentInfoDto, importFailList);
//                    continue;
//                }
//                //判断身份证是否在系统中唯一
///*                Map<String, Object> params = new HashMap();
//                params.put("idCard", studentIdCard);
//                List<UserInfo> userInfoList = userInfoMapper.getListByMapParams(params);
//                if (CollectionUtils.isNotEmpty(userInfoList)) {
//                    String fieldErrorMsg = ExcelErrorTipUtil.fieldErrorTip(ErrorCode.NO_EXIST_ERROR, ExcelFieldUtil.ID_CARD, ExcelFieldUtil.ID_CARD);
//                    ExcelErrorTipUtil.validField(fieldErrorMsg, studentInfoDto, importFailList);
//                    continue;
//                }*/
//            }
            //家长1, 11=姓名, 12=关系*, 13=手机号码*
            //家长1 姓名
            //1、非必填
            //2、姓名中无特殊符号，无空格
            //3、当家长姓名为空时，自动拼接家长姓名：（学生姓名+家长称呼）
//            String familyName1 = objects[11].toString();
//            String relationTypeName1 = objects[12].toString();
//            String familyMobile1 = objects[13].toString();
//            //家长2
//            String familyName2 = objects[14].toString();
//            String relationTypeName2 = objects[15].toString();
//            String familyMobile2 = objects[16].toString();
//            //家长3
//            String familyName3 = objects[17].toString();
//            String relationTypeName3 = objects[18].toString();
//            String familyMobile3 = objects[19].toString();
//            //家长4
//            String familyName4 = objects[20].toString();
//            String relationTypeName4 = objects[21].toString();
//            String familyMobile4 = objects[22].toString();
//            //家长5
//            String familyName5 = objects[23].toString();
//            String relationTypeName5 = objects[24].toString();
//            String familyMobile5 = objects[25].toString();
//            //家长6
//            String familyName6 = objects[26].toString();
//            String relationTypeName6 = objects[27].toString();
//            String familyMobile6 = objects[28].toString();
//            //家长7
//            String familyName7 = objects[29].toString();
//            String relationTypeName7 = objects[30].toString();
//            String familyMobile7 = objects[31].toString();

            //姓名去空,去重
//            Map<Integer, String> nameMap = new HashMap();
//            nameMap.put(1, familyName1);
//            nameMap.put(2, familyName2);
//            nameMap.put(3, familyName3);
//            nameMap.put(4, familyName4);
//            nameMap.put(5, familyName5);
//            nameMap.put(6, familyName6);
//            nameMap.put(7, familyName7);
//            Boolean familyNameFlag = false;
//            for (Map.Entry<Integer, String> entry : nameMap.entrySet()) {
//                Integer num = entry.getKey();
//                String familyName = entry.getValue();
//                familyNameFlag = ExcelErrorTipUtil.checkUserNameField(familyName, String.format(ExcelFieldUtil.FAMILY_NAME, num), studentInfoDto, importFailList, false);
//                if (familyNameFlag) {
//                    break;
//                }
//            }
//            if (familyNameFlag) {
//                continue;
//            }
            //关系去空
//            Map<Integer, String> relationTypeMap = new HashMap();
//            relationTypeMap.put(1, relationTypeName1);
//            relationTypeMap.put(2, relationTypeName2);
//            relationTypeMap.put(3, relationTypeName3);
//            relationTypeMap.put(4, relationTypeName4);
//            relationTypeMap.put(5, relationTypeName5);
//            relationTypeMap.put(6, relationTypeName6);
//            relationTypeMap.put(7, relationTypeName7);
//            Boolean relationFlag = false;
//            for (Map.Entry<Integer, String> entry : relationTypeMap.entrySet()) {
//                Boolean isRequest = false;
//                Integer num = entry.getKey();
//                String familyRelation = entry.getValue();
//                if (num == 1) {
//                    isRequest = true;
//                }
//                relationFlag = ExcelErrorTipUtil.checkFamilyRelationField(familyRelation, String.format(ExcelFieldUtil.FAMILY_RELATION, num), studentInfoDto, importFailList, isRequest);
//                if (relationFlag) {
//                    break;
//                }
//            }
//            if (relationFlag) {
//                continue;
//            }
//            //手机号去空去重
//            Map<Integer, String> mobileMap = new HashMap();
//            mobileMap.put(1, familyMobile1);
//            mobileMap.put(2, familyMobile2);
//            mobileMap.put(3, familyMobile3);
//            mobileMap.put(4, familyMobile4);
//            mobileMap.put(5, familyMobile5);
//            mobileMap.put(6, familyMobile6);
//            mobileMap.put(7, familyMobile7);
//            Boolean familyMobileFlag = false;
//            for (Map.Entry<Integer, String> entry : mobileMap.entrySet()) {
//                Boolean isRequest = false;
//                Integer num = entry.getKey();
//                if (num == 1) {
//                    isRequest = true;
//                }
//                String familyMobile = entry.getValue();
//                familyMobileFlag = ExcelErrorTipUtil.checkMobileField(familyMobile, String.format(ExcelFieldUtil.FAMILY_MOBILE, num), studentInfoDto, importFailList, isRequest);
//                if (familyMobileFlag) {
//                    break;
//                }
//            }
//            if (familyMobileFlag) {
//                continue;
//            }
//            //去掉空的mobile
//            List<String> mobiles = new ArrayList<>();
//            addMobileToList(mobiles, studentMobile);
//            addMobileToList(mobiles, familyMobile1);
//            addMobileToList(mobiles, familyMobile2);
//            addMobileToList(mobiles, familyMobile3);
//            addMobileToList(mobiles, familyMobile4);
//            addMobileToList(mobiles, familyMobile5);
//            addMobileToList(mobiles, familyMobile6);
//            addMobileToList(mobiles, familyMobile7);
//            //List转Set,校验手机号是否行内重复,包括学生和家长或者家长与家长之间手机号是否重复,如果重复,不需要去数据库中查询系统中是否重复
//            Set mobileSet = new HashSet(mobiles);
//            if (mobiles.size() != mobileSet.size()) {
//                ExcelErrorTipUtil.validField(ErrorCode.MOBILE_DUPLICATE_ERROR, studentInfoDto, importFailList);
//                continue;
//            }

            if (null != newOrgId) {
                //构建学生对象
//                StudentInfoDto studentInfo = new StudentInfoDto();
                studentInfoDto.setOrgId(newOrgId);
                studentInfoDto.setGradeId(newClassInfo.getGradeId());
                studentInfoDto.setClassId(newClassInfo.getId());
//                studentInfoDto.setClassName(className);
//                studentInfoDto.setName(studentName);
//                studentInfoDto.setSex(sex);
//                studentInfoDto.setStudentNo(studentNo);
//                studentInfoDto.setBirthDate(birthDate);
//                studentInfoDto.setEnterDate(enterDate);
//                studentInfoDto.setNationality(nationality);
//                studentInfoDto.setIdCard(studentIdCard);
//                studentInfoDto.setMobile(studentMobile);
                //JSON格式,支持一个卡号和多个卡号,多个卡号用逗号分隔
//                if (StringUtil.isNotEmpty(studentCardNo)) {
//                    studentInfo.setCardNo(Arrays.asList(studentCardNo.split(",")));
//                }
                //7个家长
                List<FamilyInfoDto> familyInfoList = new LinkedList();
//                familyInfoList.add(getFamilyInfo(familyName1, relationTypeName1, familyMobile1, true));
//                familyInfoList.add(getFamilyInfo(familyName2, relationTypeName2, familyMobile2, true));
//                familyInfoList.add(getFamilyInfo(familyName3, relationTypeName3, familyMobile3, false));
//                familyInfoList.add(getFamilyInfo(familyName4, relationTypeName4, familyMobile4, false));
//                familyInfoList.add(getFamilyInfo(familyName5, relationTypeName5, familyMobile5, false));
//                familyInfoList.add(getFamilyInfo(familyName6, relationTypeName6, familyMobile6, false));
//                familyInfoList.add(getFamilyInfo(familyName7, relationTypeName7, familyMobile7, false));

//                importNewUser(userDto, newOrgId, newClassInfo, studentInfo,familyInfoList,importOkList,importFailList);
                importUser(userDto, studentInfoDto, familyInfoList, importOkList, importFailList, isClearAddressBook);
            }
            currentRow++;
        }

        saveImportLog(userDto, newOrgId, importOkList, importFailList);

        returnMap.put("success", importOkList);
        returnMap.put("fail", importFailList);

        if (importFailList.size() > 0){
            ResultDTO<Map<String,Object>> failResult =  ResultDTO.errorResult("导入成功"+importOkList.size()+"个，导入失败"+importFailList.size()+"个\n异常详情："+JsonUtil.objectToJson(importFailList));
            return failResult;
        }
        return new ResultDTO();
    }

    /**
     * 校验学号
     *
     * @param orgId
     * @param studentNo
     * @return
     */
    private List<Student> checkStudentNoUnique(Long orgId, String studentNo, Long classId) {
        Map<String, Object> params = new HashMap();
        params.put("orgId", orgId);
        params.put("studentNo", studentNo);
        params.put("classId", classId);
        List<Student> studentList = studentMapper.getListByMapParams(params);
        return studentList;
    }

    //save到数据库
    private void saveImportLog(UserDto userDto, Long newOrgId, List<StudentInfoDto> importOkList, List<StudentInfoDto> importFailList) {
        if (CollectionUtils.isNotEmpty(importFailList)) {
            importLogService.addImportLog(userDto, newOrgId, Short.valueOf("2"), false, JSONObject.toJSONString(importFailList));
        }
        if (CollectionUtils.isNotEmpty(importOkList)) {
            importLogService.addImportLog(userDto, newOrgId, Short.valueOf("2"), true, JSONObject.toJSONString(importOkList));
        }
    }

    private FamilyInfoDto getFamilyInfo(String familyName, String relationTypeName, String familyMobile, Boolean showAddressBook) {
        FamilyInfoDto familyInfo = new FamilyInfoDto();
        familyInfo.setName(familyName);
        familyInfo.setRelationType(RelationTypeEnum.getValue(relationTypeName));
        familyInfo.setRelationTypeName(relationTypeName);
        familyInfo.setMobile(familyMobile);
        familyInfo.setShowAddressBook(showAddressBook);
        return familyInfo;
    }

    /**
     * 只显示学校名称,班级,学生姓名,(学号),家长关系,家长手机号,失败原因
     *
     * @param objects
     * @return
     */
    private StudentInfoDto changeToEntityForNew(Object[] objects) {
        StudentInfoDto studentInfoDto = new StudentInfoDto();
        studentInfoDto.setOrgName(objects[0].toString());
        studentInfoDto.setGradeName(objects[1].toString());
        studentInfoDto.setClassName(objects[2].toString());
        studentInfoDto.setName(objects[3].toString());
        studentInfoDto.setSex(objects[4].toString());
        studentInfoDto.setStudentNo(objects[5].toString());
//        studentInfoDto.setRelationTypeName(objects[12].toString());
//        studentInfoDto.setFamilyMobile(objects[13].toString());
        return studentInfoDto;
    }

    private List<String> addMobileToList(List<String> list, String str) {
        if (!StringUtils.isEmpty(str)) {
            list.add(str);
        }
        return list;
    }

    private void importUser(UserDto userDto, StudentInfoDto studentInfoDto, List<FamilyInfoDto> familyInfoList, List<StudentInfoDto> importOkList, List<StudentInfoDto> importFailList, Boolean isClearAddressBook) throws Exception {
        StudentManageEditVo studentManageEditVo = new StudentManageEditVo();
        //处理familyInfoList,去掉mobile和relationTypeName为空的family,因为此family不保存
        //保存家长信息(7个家长信息)//家长姓名为空,并且与学生关系不为空时候,拼接家长姓名=学生姓名+昵称
        Iterator<FamilyInfoDto> iterator = familyInfoList.iterator();
        while (iterator.hasNext()) {
            FamilyInfoDto familyInfo = iterator.next();
            if (!StringUtil.isEmpty(familyInfo.getMobile()) && !StringUtil.isEmpty(familyInfo.getRelationTypeName())) {
                familyInfo.setOrgId(studentInfoDto.getOrgId());
                familyInfo.setGradeId(studentInfoDto.getGradeId());
                familyInfo.setClassId(studentInfoDto.getClassId());
                if (!StringUtil.isEmpty(studentInfoDto.getName()) && StringUtil.isEmpty(familyInfo.getName())) {
                    familyInfo.setName(new StringBuffer(studentInfoDto.getName()).append(familyInfo.getRelationTypeName()).toString());
                }
                //这里是否需要再次判断roleType?
                User user = userService.checkUserMobile(familyInfo.getMobile());
                if (null != user) {
                    familyInfo.setUserId(user.getId());
                }
            } else {
                iterator.remove();
            }
        }

        Boolean isExist = checkStudentExist(studentInfoDto, familyInfoList);
        log.info("----importUser----studentUserId={},isExist={}", studentInfoDto.getUserId(), isExist);
        if (isExist) {
            String fieldErrorMsg = ExcelErrorTipUtil.fieldErrorTip(ErrorCode.USER_EXIST_ERROR, ExcelFieldUtil.STUDENT);
            ExcelErrorTipUtil.validField(fieldErrorMsg, studentInfoDto, importFailList);
            return;
        }
        studentManageEditVo.setStudentInfoDto(studentInfoDto);
        studentManageEditVo.setFamilyInfoList(familyInfoList);
        insert(studentManageEditVo, userDto.getName(), false, isClearAddressBook);
        ExcelErrorTipUtil.validField(ErrorCode.IMPORT_SUCCESS, studentInfoDto, importOkList);
    }

    //检查学生studentId是否已经存在
    private Boolean checkStudentExist(StudentInfoDto studentInfo, List<FamilyInfoDto> familyInfoList) {
        Boolean isExist = false;
        Long newOrgId = studentInfo.getOrgId();
        Long newClassId = studentInfo.getClassId();
        String studentName = studentInfo.getName();
        String mobile = studentInfo.getMobile();
        if (StringUtil.isNotEmpty(mobile)) {
            //判断是否已存在
            User user = userService.checkUserMobile(mobile);
            if (null != user) {
                Boolean flag = ExcelErrorTipUtil.checkRoleExist(newOrgId, user.getRoleType());
                if (flag || ExcelErrorTipUtil.checkTouristRole(user.getRoleType())) {
                    studentInfo.setUserId(user.getId());
                } else {
                    isExist = true;
                }
            }
        } else {
            Map<String, Object> studentParams = new HashMap<String, Object>();
            studentParams.put("orgId", newOrgId);
            studentParams.put("classId", newClassId);
            studentParams.put("studentName", studentName);
            Student student = studentMapper.getUniqueByMapParams(studentParams);
            //在学校 班级  姓名 查出有重复的情况下，再根据家长手机号判断一下,只要有一个家长手机号相同就认为是同一个人
            if (null != student) {
                Set<String> mobileList = new HashSet<>();
                for (FamilyInfoDto familyInfo : familyInfoList) {
                    if (!StringUtils.isEmpty(familyInfo.getMobile())) {
                        mobileList.add(familyInfo.getMobile());
                    }
                }
                Map<String, Object> familyParams = new HashMap<String, Object>();
                familyParams.put("orgId", newOrgId);
                familyParams.put("classId", newClassId);
                familyParams.put("studentId", student.getUserId());
                if (null != mobileList && mobileList.size() > 0) {
                    familyParams.put("mobileList", mobileList);
                }
                familyParams.put("status", 1);
                Family family = familyMapper.getByMapParams(familyParams);
                if (null != family) {
                    log.info("----学生已存在,重复导入----newOrgId={},newClassId={},studentName={},mobile={}", newOrgId, newClassId, studentName, mobile);
                    User user = userMapper.getByPrimaryKey(student.getUserId());
                    Boolean flag = ExcelErrorTipUtil.checkRoleExist(newOrgId, user.getRoleType());
                    if (flag || ExcelErrorTipUtil.checkTouristRole(user.getRoleType())) {
                        studentInfo.setUserId(user.getId());
                    } else {
                        isExist = true;
                    }
                }
            }
        }
        return isExist;
    }

    private void importNewUser(UserDto userDto, Long newOrgId, ClassInfo newClassInfo, StudentInfoDto studentInfo, List<FamilyInfoDto> familyInfoList, List<StudentInfoDto> importOkList, List<StudentInfoDto> importFailList) throws Exception {
        //保存学生信息(1个学生信息)
        Long studentUserId = saveStudent(userDto, newOrgId, newClassInfo, studentInfo, familyInfoList);
        if (studentUserId == null) {
            String fieldErrorMsg = ExcelErrorTipUtil.fieldErrorTip(ErrorCode.USER_EXIST_ERROR, ExcelFieldUtil.STUDENT);
            ExcelErrorTipUtil.validField(fieldErrorMsg, studentInfo, importFailList);
            return;
        }
        //保存家长信息(7个家长信息)//家长姓名为空,并且与学生关系不为空时候,拼接家长姓名=学生姓名+昵称
        for (FamilyInfoDto familyInfo : familyInfoList) {
            if (!StringUtil.isEmpty(familyInfo.getMobile()) && !StringUtil.isEmpty(familyInfo.getRelationTypeName())) {
                if (!StringUtil.isEmpty(studentInfo.getName()) && StringUtil.isEmpty(familyInfo.getName())) {
                    familyInfo.setName(new StringBuffer(studentInfo.getName()).append(familyInfo.getRelationTypeName()).toString());
                }
                saveFamily(userDto, newOrgId, newClassInfo, studentUserId, familyInfo);
            }
        }
        ExcelErrorTipUtil.validField(ErrorCode.IMPORT_SUCCESS, studentInfo, importOkList);
    }

    private Long saveStudent(UserDto userDto, Long newOrgId, ClassInfo newClassInfo, StudentInfoDto studentInfo, List<FamilyInfoDto> familyInfoList) throws Exception {
        Long newClassId = newClassInfo.getId();
        String studentName = studentInfo.getName();
        String mobile = studentInfo.getMobile();
        log.info("----importNewUser参数:----newOrgId={},newClassId={},studentName={},mobile={}", newOrgId, newClassId, studentName, mobile);
        //先判断是否同一个学生(不能同一个人重复导入)
        if (StringUtil.isNotEmpty(mobile)) {
            //判断是否已存在
            User user = userService.checkUserMobile(mobile);
            if (null == user) {
                return saveStudentInfo(userDto, newClassInfo, studentInfo);
            } else {
                //以下两种情况需要合并roleType
                //2、如果是游客需要合并身份
                //3、导入学生时,只有一个不同学校的学生身份才能进行身份合并,否则不进行身份合并
                Boolean flag = ExcelErrorTipUtil.checkRoleExist(newOrgId, user.getRoleType());
                if (flag || ExcelErrorTipUtil.checkTouristRole(user.getRoleType())) {
                    updateStudentInfo(userDto, newOrgId, newClassInfo, studentInfo, user.getId());
                    return user.getId();
                } else {
                    return null;
                }
            }
        } else {
            Map<String, Object> studentParams = new HashMap<String, Object>();
            studentParams.put("orgId", newOrgId);
            studentParams.put("classId", newClassId);
            studentParams.put("studentName", studentName);
            Student student = studentMapper.getUniqueByMapParams(studentParams);
            //在学校 班级  姓名 查出有重复的情况下，再根据家长手机号判断一下,只要有一个家长手机号相同就认为是同一个人
            if (null != student) {
                Set<String> mobileList = new HashSet<>();
                for (FamilyInfoDto familyInfo : familyInfoList) {
                    if (!StringUtils.isEmpty(familyInfo.getMobile())) {
                        mobileList.add(familyInfo.getMobile());
                    }
                }
                Map<String, Object> familyParams = new HashMap<String, Object>();
                familyParams.put("orgId", newOrgId);
                familyParams.put("classId", newClassId);
                familyParams.put("studentId", student.getUserId());
                familyParams.put("mobileList", mobileList);
                familyParams.put("status", 1);
                Family family = familyMapper.getByMapParams(familyParams);
                if (null != family) {
                    log.info("----学生已存在,重复导入----newOrgId={},newClassId={},studentName={},mobile={}", newOrgId, newClassId, studentName, mobile);
                    User user = userMapper.getByPrimaryKey(student.getUserId());
                    Boolean flag = ExcelErrorTipUtil.checkRoleExist(newOrgId, user.getRoleType());
                    if (flag || ExcelErrorTipUtil.checkTouristRole(user.getRoleType())) {
                        updateStudentInfo(userDto, newOrgId, newClassInfo, studentInfo, student.getUserId());
                        return student.getUserId();
                    } else {
                        return null;
                    }
                }
            }
            return saveStudentInfo(userDto, newClassInfo, studentInfo);
        }
    }

    private void saveFamily(UserDto userDto, Long orgId, ClassInfo newClassInfo, Long studentUserId, FamilyInfoDto familyInfo) throws Exception {
        User user = userService.checkUserMobile(familyInfo.getMobile());
        if (null == user) {
            addFamilyInfo(userDto, orgId, newClassInfo, studentUserId, familyInfo);
        } else {
            Boolean flag = ExcelErrorTipUtil.checkRoleExist(user.getRoleType());
            Boolean isTourist = ExcelErrorTipUtil.checkTouristRole(user.getRoleType());
            log.info("---开始合并身份---flag={},isTourist={}", flag, isTourist);
            if (!flag || isTourist) {
                log.info("---开始合并身份---studentUserId={},familyInfo={}", studentUserId, JSONObject.toJSONString(familyInfo));
                updateFamilyInfo(userDto, orgId, newClassInfo, studentUserId, familyInfo, user.getId());
            }
        }
    }

    private Boolean checkMobile(Long orgId, List<String> mobiles, Integer roleType) {
        //判断手机号码是否已经存在于系统中,如果已经存在,则不导入此老师数据
        Boolean isExist = false;
        for (String mobile : mobiles) {
            UserInfoDto userInfoDto = userService.checkMobileUnique(orgId, mobile, roleType);
            if (null != userInfoDto) {
                isExist = true;
            }
        }
        return isExist;
    }

    private Long saveStudentInfo(UserDto userDto, ClassInfo newClassInfo, StudentInfoDto studentInfo) {
        String sex = studentInfo.getSex();
        Date birthDate = studentInfo.getBirthDate();

        //如果性别为空,则性别默认为男性
        if (StringUtils.isEmpty(sex)) {
            sex = "男";
        }
        User user = new User();
        user.setName(studentInfo.getName());
        //先按照一个单个角色来导入
        //[{"orgId": 1, "roleTypes": [{"roleType": 3, "roleTypeName": "学生"}]}]
        JSONArray jsonArray = new JSONArray();
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("orgId", newClassInfo.getOrgId());

        JSONArray roleTypesArray = new JSONArray();
        JSONObject roleTypesObject = new JSONObject();
        roleTypesObject.put("roleType", RoleTypeEnum.STUDENT.getValue());
        roleTypesObject.put("roleTypeName", RoleTypeEnum.STUDENT.getDesc());
        roleTypesArray.add(roleTypesObject);

        jsonObject.put("roleTypes", roleTypesArray);
        jsonArray.add(jsonObject);
        user.setRoleType(jsonArray);
        user.setUserCode(UuIdUtil.getUserCodeByUUId());
        user.setMobile(studentInfo.getMobile());
        user.setStatus(true);
        String headImgUrl = FillEmptyHeadImgUtil.checkHeadImg(sex, RoleTypeEnum.STUDENT.getValue(), "", false);
        if (StringUtil.isNotEmpty(headImgUrl)) {
            user.setHeadImgUrl(headImgUrl);
        }
        userMapper.insert(user);

        //得到insert之后的新的userId
        Long newStudentUserId = user.getId();
        UserInfo userInfo = new UserInfo();
        userInfo.setUserId(newStudentUserId);
        userInfo.setSex(sex);
        userInfo.setBirthDate(birthDate);
        userInfo.setNationality(studentInfo.getNationality());
//        userInfo.setIdcard(studentInfo.getIdcard());
        if (StringUtil.isNotEmpty(user.getHeadImgUrl())) {
            userInfo.setHeadImgMd5(userService.getImageMD5(user.getHeadImgUrl()));
        }
        userInfoMapper.insert(userInfo);

        insertStudent(userDto, newClassInfo, newStudentUserId, studentInfo);

        return newStudentUserId;
    }

    private void insertStudent(UserDto userDto, ClassInfo newClassInfo, Long newStudentUserId, StudentInfoDto studentInfo) {
        //保存学生信息
        Student student = new Student();
        student.setOrgId(newClassInfo.getOrgId());
        student.setUserId(newStudentUserId);
        student.setGradeId(newClassInfo.getGradeId());
        student.setClassId(newClassInfo.getId());
        student.setMobile(studentInfo.getMobile());
        student.setEnterDate(studentInfo.getEnterDate());
        student.setStudentNo(studentInfo.getStudentNo());
        student.setCardNo(studentInfo.getCardNo());
        student.setStatus(true);
        student.setCreateBy(userDto.getName());
        student.setUpdateBy(userDto.getName());
        student.setAutoCreate(false);
        studentMapper.insert(student);
        //学生班级关联
        studentMapper.insertClassStudent(student);
    }

    //先判断是否同一个家长（不能同一个人重复导入）
    private Boolean checkStudentExist(Long orgId, String mobile, Long studentUserId) {
        Boolean isExist = false;
        Map<String, Object> paramsMap = new HashMap<String, Object>();
        paramsMap.put("orgId", orgId);
        paramsMap.put("mobile", mobile);
        paramsMap.put("userId", studentUserId);
        Student student = studentMapper.getByMapParams(paramsMap);
        if (null != student) {
            isExist = true;
        }
        return isExist;
    }

    private void updateStudentInfo(UserDto userDto, Long orgId, ClassInfo newClassInfo, StudentInfoDto studentInfo, Long studentUserId) throws Exception {
        String mobile = studentInfo.getMobile();
        String studentName = studentInfo.getName();
        Boolean isExist = checkStudentExist(orgId, mobile, studentUserId);
        if (isExist) {
            return;
        }

        //修改USER表roleType
        User user = userMapper.getByPrimaryKey(studentUserId);

        Object roleType = userService.updateRoleTypeJson(user.getRoleType(), null, Short.parseShort("" + RoleTypeEnum.STUDENT.getValue()), null, orgId, user.getId());
        user.setRoleType(roleType);
        user.setName(studentName);
        userService.update(orgId, user, RoleTypeEnum.STUDENT.getValue(), false, null, false);

        insertStudent(userDto, newClassInfo, studentUserId, studentInfo);
    }

    private void addFamilyInfo(UserDto userDto, Long orgId, ClassInfo newClassInfo, Long studentUserId, FamilyInfoDto familyInfo) {
        String mobile = familyInfo.getMobile();
        String familyName = familyInfo.getName();
        String relationTypeName = familyInfo.getRelationTypeName();
        if (!StringUtils.isEmpty(mobile)) {
            Long oriUserId = null;
            Boolean isExist = checkFamilyExist(orgId, mobile, studentUserId, oriUserId);
            if (isExist) {
                return;
            }

            User user = new User();
            user.setName(familyName);
            //先按照一个单个角色来导入
            //[{"orgId": 1, "roleTypes": [{"roleType": 2, "roleTypeName": "家长"}]}]
            JSONArray jsonArray = new JSONArray();
            JSONObject jsonObject = new JSONObject();
            jsonObject.put("orgId", newClassInfo.getOrgId());

            JSONArray roleTypesArray = new JSONArray();
            JSONObject roleTypesObject = new JSONObject();
            roleTypesObject.put("roleType", RoleTypeEnum.FAMILY.getValue());
            roleTypesObject.put("roleTypeName", RoleTypeEnum.FAMILY.getDesc());
            roleTypesArray.add(roleTypesObject);

            jsonObject.put("roleTypes", roleTypesArray);
            jsonArray.add(jsonObject);
            user.setRoleType(jsonArray);
            user.setUserCode(UuIdUtil.getUserCodeByUUId());
            user.setMobile(mobile);
            user.setStatus(true);

            String sex = FillEmptyHeadImgUtil.checkFamilySex(RelationTypeEnum.getValue(relationTypeName));
            String headImgUrl = FillEmptyHeadImgUtil.checkHeadImg(sex, RoleTypeEnum.FAMILY.getValue(), "", false);
            if (StringUtil.isNotEmpty(headImgUrl)) {
                user.setHeadImgUrl(headImgUrl);
            }
            userMapper.insert(user);

            //得到insert之后的新的userId
            Long newUserId = user.getId();
            UserInfo userInfo = new UserInfo();
            userInfo.setUserId(newUserId);
            //设置性别
            if (StringUtil.isNotEmpty(sex)) {
                userInfo.setSex(sex);
            }
            //设置头像
            if (StringUtil.isNotEmpty(user.getHeadImgUrl())) {
                userInfo.setHeadImgMd5(userService.getImageMD5(user.getHeadImgUrl()));
            }
            userInfoMapper.insert(userInfo);

            insertFamily(userDto, newClassInfo, newUserId, mobile, studentUserId, relationTypeName);
        }
    }

    private void updateFamilyInfo(UserDto userDto, Long orgId, ClassInfo newClassInfo, Long studentUserId, FamilyInfoDto familyInfo, Long oriUserId) throws Exception {
        String mobile = familyInfo.getMobile();
        String familyName = familyInfo.getName();
        String relationTypeName = familyInfo.getRelationTypeName();
        if (!StringUtils.isEmpty(mobile)) {

            Boolean isExist = checkFamilyExist(orgId, mobile, studentUserId, oriUserId);
            if (isExist) {
                return;
            }
            log.info("----正在合并身份----orgId={},mobile={},studentUserId={}", orgId, mobile, studentUserId);
            //修改USER表roleType
            User user = userMapper.getByPrimaryKey(oriUserId);

            Object roleType = userService.updateRoleTypeJson(user.getRoleType(), null, Short.parseShort("" + RoleTypeEnum.FAMILY.getValue()), null, orgId, user.getId());
            user.setRoleType(roleType);
            //导入家长时候,多身份,name为空则使用家长覆盖
            if (StringUtil.isEmpty(user.getName())) {
                user.setName(familyName);
            }
            userService.update(orgId, user, RoleTypeEnum.FAMILY.getValue(), false, null, false);

            insertFamily(userDto, newClassInfo, oriUserId, mobile, studentUserId, relationTypeName);
        }
    }

    //先判断是否同一个家长（不能同一个人重复导入）
    private Boolean checkFamilyExist(Long orgId, String mobile, Long studentUserId, Long userId) {
        Boolean isExist = false;
        Map<String, Object> familyParams = new HashMap<String, Object>();
        familyParams.put("orgId", orgId);
        familyParams.put("mobile", mobile);
        familyParams.put("userId", userId);
        familyParams.put("studentId", studentUserId);
        familyParams.put("status", 1);
        Family family = familyMapper.getByMapParams(familyParams);
        if (null != family) {
            isExist = true;
        }
        return isExist;
    }

    private void insertFamily(UserDto userDto, ClassInfo newClassInfo, Long newUserId, String mobile, Long studentUserId, String relationTypeName) {
        Family familyInfo = new Family();
        familyInfo.setOrgId(newClassInfo.getOrgId());
        familyInfo.setUserId(newUserId);
        familyInfo.setGradeId(newClassInfo.getGradeId());
        familyInfo.setClassId(newClassInfo.getId());
        familyInfo.setMobile(mobile);
        familyInfo.setStudentUserId(studentUserId);
        familyInfo.setRelationType(RelationTypeEnum.getValue(relationTypeName));
        familyInfo.setShowAddressBook(true);
        familyInfo.setStatus(true);
        familyInfo.setCreateBy(userDto.getName());
        familyInfo.setUpdateBy(userDto.getName());
        familyMapper.insert(familyInfo);
    }

    @Override
    public McStudentInfoDto getByCardNo(Map<String, Object> params) throws Exception {
        return studentMapper.getByCardNo(params);
    }

    @Override
    public StudentInfoDto getStudentInfoByMapParams(Map<String, Object> params) {
        return studentMapper.getStudentInfoByMapParams(params);
    }

    @Override
    public List<Map<String, Object>> getStudentStatByGrade(Long orgId) {
        return studentMapper.getStudentStatByGrade(orgId);
    }

    @Override
    public List<Map<String, Object>> getStudentStatBySex(Long orgId) {
        return studentMapper.getStudentStatBySex(orgId);
    }

    private String getDeleteName(String statusName, String name, Boolean flag) {
        //这是失败
        if (StringUtil.isEmptyIgnoreBlank(statusName) && !flag) {
            return "以下人员存在未过期订单,确认删除:" + name;
        }
        return statusName + "、" + name;
    }

    @Override
    public List<Long> getStudentUserIdByParam(Long orgId, Long gradeId, Long classId, String keyWord) {
        HashMap<String, Object> param = new HashMap<>(4);
        param.put("orgId", orgId);
        param.put("gradeId", gradeId);
        param.put("classId", classId);
        param.put("keyWord", keyWord);
        return studentMapper.getStudentUserIdByParam(param);
    }

    @Override
    public PageInfo<PayUserCommodityInfoDto> getUserPackageByParam(List<Long> userIds, Integer pageNo, Integer pageSize) {
        Page<PayUserCommodityInfoDto> page = PageHelper.startPage(pageNo, pageSize, true);
        HashMap<String, Object> param = new HashMap<>(1);
        param.put("userIds", userIds);

        PageInfo<PayUserCommodityInfoDto> pageInfo = new PageInfo<>(
                studentMapper.getUserPackageByParam(param)
        );

        pageInfo.setTotal(page.getTotal());
        return pageInfo;
    }

    @Override
    public List<Object[]> exportStudentInfoExcel(Map<String, Object> params) throws Exception {
        Long orgId = (Long) params.get("orgId");
        OrganizationDto organizationDto = organizationService.getInfo(orgId);

        List<StudentInfoDto> familyList = studentMapper.getStudentFamilyList(params);
        log.info("********exportStudentInfoExcel orgId:{} size:{}", orgId, familyList.size());
        if (CollectionUtils.isNotEmpty(familyList)) {

            List<Object[]> data = new ArrayList<>(familyList.size());

            //返回教职工数据
            familyList.forEach(e -> {

                String strCardNo = "";
                Object cardNo = e.getCardNo();
                if (null != cardNo) {
                    JSONArray jsonArray = JSON.parseArray(JSON.toJSONString(cardNo));
                    for (int i = 0; i < jsonArray.size(); i++) {
                        strCardNo = strCardNo + " " + jsonArray.get(i);
                    }
                }

                Object[] d = new Object[8];
                int i = 0;
                d[i++] = organizationDto.getName() == null ? "-" : organizationDto.getName();
                d[i++] = e.getName() == null ? "-" : e.getName();
                d[i++] = e.getClassName() == null ? "-" : e.getClassName();
                d[i++] = e.getStudentNo() == null ? "-" : e.getStudentNo();
                d[i++] = StringUtil.isEmpty(e.getMobile()) ? "-" : e.getMobile();
                d[i++] = StringUtil.isEmpty(strCardNo) ? "-" : strCardNo;
                d[i++] = e.getHasUploadFace() == true ? "已上传" : "未上传";
                d[i++] = StringUtil.isEmptyIgnoreBlank(e.getCreateTime()) ? "-" : e.getCreateTime();
                data.add(d);
            });
            return data;
        }

        return null;
    }

    @Override
    public void changeClassForStudent(Long orgId, Long newClassId, Long userId, String operateUser) {
        log.info("***changeClassForStudent****orgId:{} newClassId:{} userId:{}", orgId, newClassId, userId);
        try {
            StudentManageEditVo studentManageEditVo = new StudentManageEditVo();

            //查询学生信息
            HashMap<String, Object> studentParams = new HashMap<>();
            studentParams.put("orgId", orgId);
            studentParams.put("userId", userId);
            StudentInfoDto studentInfoDto = studentMapper.getStudentInfoByMapParams(studentParams);
            Long orignClassId = studentInfoDto.getClassId();
            log.info("***userId:{} classId:{} orignClassId:{}", userId, newClassId, orignClassId);
            if (!newClassId.equals(studentInfoDto.getClassId())) {

                //查询待调换的班级信息
                ClassInfo classInfo = classInfoMapper.getByPrimaryKey(newClassId);
                Grade grade = gradeMapper.getByPrimaryKey(classInfo.getGradeId());

                //更换班级
                studentInfoDto.setGradeId(classInfo.getGradeId());//设置年级
                studentInfoDto.setClassId(newClassId);//设置班级
                studentInfoDto.setOriClassId(orignClassId);//设置原班级

                //查询家长信息
                HashMap<String, Object> familyParams = new HashMap<>();
                familyParams.put("orgId", orgId);
                familyParams.put("userId", userId);
                List<FamilyInfoDto> familyInfoList = familyService.getFamilyListByStudent(familyParams);
                for (FamilyInfoDto familyInfoDto : familyInfoList) {
                    familyInfoDto.setGradeId(classInfo.getGradeId());//设置年级
                    familyInfoDto.setClassId(newClassId);//设置班级
                }

                studentManageEditVo.setStudentInfoDto(studentInfoDto);
                studentManageEditVo.setFamilyInfoList(familyInfoList);

                //更新学生
                log.info("****{}开始换班****", userId);
                this.update(studentManageEditVo, operateUser, true);

                //同步数据到动态
                ThreadPoolUtil.addPoolTask(new ChangeClassSyncDataTask(ChangeClassOperateTypeEnum.CHANGE_CLASS_TO_STUDENT_PERSON.getCode(), doorFeignService, orgId, grade.getId(), grade.getGradeName(), classInfo.getId(), classInfo.getClassName(), userId, operateUser));
            }

        } catch (Exception e) {
            log.error("***********changeClassForStudent error******", e);
        }
    }

    @Override
    public void changeGradeForStudent(Long orgId, Long newGradeId, Long userId, String operateUser) {
        log.info("***changeGradeForStudent****orgId:{} newGradeId:{} userId:{}", orgId, newGradeId, userId);
        try {
            StudentManageEditVo studentManageEditVo = new StudentManageEditVo();

            //查询学生信息
            HashMap<String, Object> studentParams = new HashMap<>();
            studentParams.put("orgId", orgId);
            studentParams.put("userId", userId);
            StudentInfoDto studentInfoDto = studentMapper.getStudentInfoByMapParams(studentParams);

            log.info("***userId:{} newGradeId:{} orignGradeId:{}", userId, newGradeId, studentInfoDto.getGradeId());
            if (!newGradeId.equals(studentInfoDto.getGradeId())) {

                //查询待调换的班级信息
                ClassInfo classInfo = classInfoMapper.getByPrimaryKey(studentInfoDto.getClassId());
                Grade grade = gradeMapper.getByPrimaryKey(newGradeId);

                //更换班级
                studentInfoDto.setGradeId(newGradeId);//设置年级
                studentInfoDto.setClassId(studentInfoDto.getClassId());//设置班级

                //查询家长信息
                HashMap<String, Object> familyParams = new HashMap<>();
                familyParams.put("orgId", orgId);
                familyParams.put("userId", userId);
                List<FamilyInfoDto> familyInfoList = familyService.getFamilyListByStudent(familyParams);
                for (FamilyInfoDto familyInfoDto : familyInfoList) {
                    familyInfoDto.setGradeId(newGradeId);//设置年级
                    familyInfoDto.setClassId(studentInfoDto.getClassId());//设置班级
                }

                studentManageEditVo.setStudentInfoDto(studentInfoDto);
                studentManageEditVo.setFamilyInfoList(familyInfoList);

                //更新学生
                log.info("****{}开始升班****", userId);
                this.update(studentManageEditVo, operateUser, true);

                //同步数据到动态
                ThreadPoolUtil.addPoolTask(new ChangeClassSyncDataTask(ChangeClassOperateTypeEnum.CHANGE_CLASS_TO_STUDENT_PERSON.getCode(), doorFeignService, orgId, grade.getId(), grade.getGradeName(), classInfo.getId(), classInfo.getClassName(), userId, operateUser));
            }

        } catch (Exception e) {
            log.error("***********changeClassForStudent error******", e);
        }
    }

    @Override
    public Student findByMapParams(Map<String, Object> map) {
        return studentMapper.findByMapParams(map);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public StudentInfoDto addStudent(StudentInfoDto studentInfoDto,boolean autoCreate) {
        studentInfoDto.setAutoCreate(autoCreate);
        String sex = studentInfoDto.getSex();
        UserInfo userInfo = new UserInfo();
        if (!autoCreate){
            studentInfoDto.setOrgId(0L);
            studentInfoDto.setClassId(0L);
            if (studentInfoDto.getUserType() == 1){
                Map<String, Object> params = new HashMap<>();
                params.put("provinceId",studentInfoDto.getProvinceCode());
                params.put("cityId",studentInfoDto.getCityCode());
                params.put("areaId",studentInfoDto.getAreaCode());
                params.put("name",studentInfoDto.getOrgName());
                userInfo.setProvince(districtMapper.getDistrictNameByCode(studentInfoDto.getProvinceCode()));
                userInfo.setCity(districtMapper.getDistrictNameByCode(studentInfoDto.getCityCode()));
                userInfo.setArea(districtMapper.getDistrictNameByCode(studentInfoDto.getAreaCode()));
                School school = schoolMapper.getByMapParams(params);
                if (school == null){
                    school = new School();
                    school.setProvinceId(studentInfoDto.getProvinceCode());
                    school.setCityId(studentInfoDto.getCityCode());
                    school.setAreaId(studentInfoDto.getAreaCode());
                    school.setProvince(userInfo.getProvince());
                    school.setCity(userInfo.getCity());
                    school.setArea(userInfo.getArea());
                    school.setName(studentInfoDto.getOrgName());
                    school.setCreateBy(studentInfoDto.getName());
                    schoolMapper.insert(school);
                }
                studentInfoDto.setSchoolId(school.getId());
            }else{
                studentInfoDto.setSchoolId(null);
                studentInfoDto.setProvinceCode(null);
                studentInfoDto.setCityCode(null);
                studentInfoDto.setAreaCode(null);
            }
        }


        //如果性别为空,则性别默认为男性
        if (StringUtils.isEmpty(sex)) {
            sex = "男";
        }
        User user = new User();
        user.setName(studentInfoDto.getName());
        //先按照一个单个角色来导入
        //[{"orgId": 1, "roleTypes": [{"roleType": 3, "roleTypeName": "学生"}]}]
        JSONArray jsonArray = new JSONArray();
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("orgId", studentInfoDto.getOrgId());

        JSONArray roleTypesArray = new JSONArray();
        JSONObject roleTypesObject = new JSONObject();
        roleTypesObject.put("roleType", RoleTypeEnum.STUDENT.getValue());
        roleTypesObject.put("roleTypeName", RoleTypeEnum.STUDENT.getDesc());
        roleTypesArray.add(roleTypesObject);

        jsonObject.put("roleTypes", roleTypesArray);
        jsonArray.add(jsonObject);
        user.setRoleType(jsonArray);
        user.setUserCode(UuIdUtil.getUserCodeByUUId());
        user.setMobile(studentInfoDto.getMobile());
        user.setStatus(true);
        String headImgUrl = FillEmptyHeadImgUtil.checkHeadImg(sex, RoleTypeEnum.STUDENT.getValue(), "", false);
        if (StringUtil.isNotEmpty(headImgUrl)) {
            user.setHeadImgUrl(headImgUrl);
        }
        userMapper.insert(user);

        //得到insert之后的新的userId
        Long newStudentUserId = user.getId();
        userInfo.setUserId(newStudentUserId);
        userInfo.setSex(sex);
        userInfo.setBirthDate(studentInfoDto.getBirthDate());
        userInfo.setNationality(studentInfoDto.getNationality());
//        userInfo.setIdcard(studentInfoDto.getIdcard());
        if (StringUtil.isNotEmpty(user.getHeadImgUrl())) {
            userInfo.setHeadImgMd5(userService.getImageMD5(user.getHeadImgUrl()));
        }
        userInfoMapper.insert(userInfo);

        //保存学生信息
        Student student = new Student();
        BeanUtils.copyProperties(studentInfoDto, student);
        student.setUserId(newStudentUserId);
        student.setStatus(true);
        studentMapper.insert(student);
        //学生班级关联
//        studentMapper.insertClassStudent(student);

        studentInfoDto.setUserId(newStudentUserId);
        return studentInfoDto;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public ResultDTO updateStudent(StudentInfoDto studentInfoDto) throws Exception {
        //当头像为空,默认设置头像.否则走正常变更
        Student student = studentMapper.getByUserId(studentInfoDto.getUserId());
        //删除前一个班级关联
        studentMapper.deleteClassStudent(student);

        User user = userMapper.getByPrimaryKey(studentInfoDto.getUserId());
        Map<String, Object> params = new HashMap<>(1);
        params.put("userId", studentInfoDto.getUserId());
        UserInfo userInfo = userInfoMapper.getByMapParams(params);
        if (user == null || student == null || userInfo == null){
            return new ResultDTO(ErrorCode.USER_NOT_EXIST);
        }


        BeanUtils.copyProperties(studentInfoDto, user);
        //copy之后会覆盖掉userId
        user.setId(studentInfoDto.getUserId());
        userMapper.update(user);

        Long oldOrgId = student.getOrgId();
        BeanUtils.copyProperties(studentInfoDto, student);

        //绑定的学生不能修改班级信息
        if (oldOrgId > 0){
            student.setOrgId(null);
            student.setOrgName(null);
            student.setGradeId(null);
            student.setGradeName(null);
            student.setClassId(null);
            student.setClassName(null);
            student.setStudentNo(null);
        }else{
            //修改学校
            if (StringUtil.isEmpty(studentInfoDto.getProvinceCode()) || StringUtil.isEmpty(studentInfoDto.getCityCode()) ||
                    StringUtil.isEmpty(studentInfoDto.getAreaCode()) || StringUtil.isEmpty(studentInfoDto.getOrgName()) ) {
                student.setOrgName(null);
                student.setSchoolId(null);
            }else{
                Map<String, Object> par = new HashMap<>();
                par.put("provinceId",studentInfoDto.getProvinceCode());
                par.put("cityId",studentInfoDto.getCityCode());
                par.put("areaId",studentInfoDto.getAreaCode());
                par.put("name",studentInfoDto.getOrgName());

                studentInfoDto.setProvince(districtMapper.getDistrictNameByCode(studentInfoDto.getProvinceCode()));
                studentInfoDto.setCity(districtMapper.getDistrictNameByCode(studentInfoDto.getCityCode()));
                studentInfoDto.setArea(districtMapper.getDistrictNameByCode(studentInfoDto.getAreaCode()));
                School school = schoolMapper.getByMapParams(par);
                if (school == null){
                    school = new School();
                    school.setProvinceId(studentInfoDto.getProvinceCode());
                    school.setCityId(studentInfoDto.getCityCode());
                    school.setAreaId(studentInfoDto.getAreaCode());
                    school.setProvince(studentInfoDto.getProvince());
                    school.setCity(studentInfoDto.getCity());
                    school.setArea(studentInfoDto.getArea());
                    school.setName(studentInfoDto.getOrgName());
                    school.setCreateBy(studentInfoDto.getName());
                    schoolMapper.insert(school);
                }
                student.setSchoolId(school.getId());
            }
        }
        studentMapper.update(student);

        BeanUtils.copyProperties(studentInfoDto, userInfo);
        if (!StringUtils.isEmpty(studentInfoDto.getHeadImgUrl())) {
            userInfo.setHeadImgMd5(userService.getImageMD5(studentInfoDto.getHeadImgUrl()));
        }
        userInfoMapper.update(userInfo);
        return ResultDTO.successResult();
    }

    @Override
    public int insertStudentFaceRecognition(StudentFaceRecognition data) {
        return studentMapper.insertStudentFaceRecognition(data);
    }

    @Override
    @Transactional(readOnly=true)
    public PageInfo<StudentInfoDto> getStudentPageList(HashMap<String, Object> params, int pageNo, int pageSize) {
        Page<StudentInfoDto> page = PageHelper.startPage(pageNo, pageSize, true);
        PageInfo<StudentInfoDto> pageInfo = new PageInfo<StudentInfoDto>(studentMapper.getStudentPageList(params));
        pageInfo.setTotal(page.getTotal());
        return pageInfo;
    }

    @Override
    public StudentDetail getStudentDetails(Long id) {

        HashMap<String, Object> params = new HashMap<>();
        params.put("studentId", id);
        List<StudentInfoDto> list = studentMapper.getStudentInfoPageList(params);
        if (!list.isEmpty()){
            StudentDetail studentDetails = new StudentDetail();
            studentDetails.setStudentInfoDto(list.get(0));
            studentDetails.setCourseClassDtos(classInfoMapper.getCourseClassByStudentId(id));
        }
        return null;
    }

    @Override
    public List<Student> findListByMapParams(Map<String, Object> map) {
        return studentMapper.findListByMapParams(map);
    }

}